﻿using Bentley.CifNET.GeometryModel;
using Bentley.CifNET.GeometryModel.DgnAccess;
using Bentley.CifNET.GeometryModel.RoadwayDesigner;
using Bentley.CifNET.LinearGeometry;
using Bentley.CifNET.Model;
using Bentley.CifNET.Objects;
using Bentley.CifNET.Objects.DataAccess;
using Bentley.CifNET.SDK.Edit;
using Bentley.GeometryNET;
using CheccCoverplateCulvertAssemble.Common;
using CheccCoverplateCulvertAssemble.Mesh;
using CheccCoverplateCulvertAssemble.run;
using CheccCulvertHelpers;
using System.Reflection;
using System.Security.AccessControl;

namespace Checc.Culvert.LayingLine;

public class CulvertLayoutParameter
{
    #region Fields

    public List<Corridor> _allRefCorridors;
    private readonly double _angleStep;
    private readonly LinearEntity2dInPlan _culvertLayoutLine;
    private readonly double _culvetSlop;
    private readonly List<LinearEntity2dInPlan> _minorAligmentList;
    private readonly IObjectSpace _objectSpace;
    private readonly LinearEntity2dInPlan _primaryAlignment;
    private readonly double _range;
    private LinearPoint _primaryIntersectPointOnCulvertLayLine;

    #endregion Fields

    #region Properties

    public DgnModel ActiveThreeDModel => this.GetActiveThreeDModelReference();

    public List<Corridor> AllRefCorridors
    {
        get
        {
            if (!this._allRefCorridors.Any())
            {
                this._allRefCorridors = this.GetAllRefCorridors();
            }
            return this._allRefCorridors;
        }
    }

    public GeometricModel GeometricModel => GeometricModel.GetGeometricModel(this._objectSpace, GetModelOptions.AllowDoNotExist);

    public LinearPoint PrimaryIntersectPointOnCulvertLayLine => this._primaryIntersectPointOnCulvertLayLine ??= this.GetPrimaryIntersectPoint();

    private unsafe DgnModel GetActiveThreeDModelReference()
    {
        DgnModelRef modelRef = DgnModelRef.GetModelRef(new IntPtr((void*)MstnPresentationEnabler.Instance.GetActiveThreeDModel()));
        return null != modelRef ? modelRef.GetDgnModel() : null;
    }

    //public Corridor PrimaryCorridor => this._primaryCorridor ??= this.GetPrimaryCorridor();

    #endregion Properties

    public CulvertLayoutParameter()
    {
    }

    public CulvertLayoutParameter(IObjectSpace objectSpace, LinearEntity2dInPlan primaryAlignment, List<LinearEntity2dInPlan> minorAligmentList, LinearEntity2dInPlan culvertLayoutLine, double angleStep, double culvetSlop)
    {
        this._objectSpace = objectSpace;
        this._primaryAlignment = primaryAlignment;
        this._minorAligmentList = minorAligmentList;
        this._culvertLayoutLine = culvertLayoutLine;
        this._angleStep = angleStep;
        this._culvetSlop = culvetSlop;
        this._allRefCorridors = new List<Corridor>();
        this._range = 100.0;
    }

    public ((DPoint3d startPoint, double slope, double normalSlope, double fillHeight, DVector3d tangentVector), (DPoint3d endPoint, double slope, double normalSlope, double fillHeight, DVector3d tangentVector)) GetCulvertLayoutInfo()
    {
        var points = this.GetPointInfoList().Where(p => p.disAlong != 0)
            .OrderBy(p => p.disAlong);
        var startPoint = points.FirstOrDefault().point;
        var endPoint = points.LastOrDefault().point;
        return ((startPoint, points.FirstOrDefault().slope, points.FirstOrDefault().normalSlope, points.FirstOrDefault().fillHeight, points.FirstOrDefault().tangentVector),
                (endPoint, points.LastOrDefault().slope, points.LastOrDefault().normalSlope, points.LastOrDefault().fillHeight, points.LastOrDefault().tangentVector));
    }

    public (CulvertPointInfo entrancePointInfo, CulvertPointInfo exitPointInfo) GetPointInfoByLength(double leftLength, double rightLength, double leftAngle, double rightAngle)
    {
        double slope = 1.0 / 1.5;
        double normalSlope = 1.0 / 1.5;
        CulvertPointInfo entrancePointInfo = null;
        CulvertPointInfo exitPointInfo = null;

        CurveVector intersectionA = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveVector intersectionB = new CurveVector(CurveVector.BoundaryType.Inner);
        //DPoint3d staPT = CommonData.Instance.linearEntity2DInPlan.ActiveLinearEntity3dValidBaseGeometry.StartPoint.Coordinates;// .CulverIntersectingLine.ActiveLinearEntity3d.LinearGeometry.StartPoint.Coordinates;
        CurveCurve.IntersectionsXY(intersectionA, intersectionB, this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), this._primaryAlignment.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
        //DPoint3d psta = this._primaryAlignment.ActiveLinearEntity3dValidBaseGeometry.StartPoint.Coordinates;
        //DPoint3d pend = this._primaryAlignment.ActiveLinearEntity3dValidBaseGeometry.EndPoint.Coordinates;
        intersectionA.GetStartPoint(out DPoint3d pointA);
        //intersectionB.GetStartPoint(out DPoint3d pt);
        DPoint3d staPoint = this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.StartPoint.Coordinates;
        DPoint3d endPoint = this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.EndPoint.Coordinates;

        DVector3d dVector3DL = new DVector3d(pointA, staPoint);
        dVector3DL.NormalizeInPlace();
        double leftL = leftLength / Math.Cos(Math.Abs(Math.Atan(this._culvetSlop / 100))); //斜边长度
        DPoint3d leftPoint = DPoint3d.Add(pointA, dVector3DL, leftL);

        DVector3d dVector3DR = new DVector3d(pointA, endPoint);
        dVector3DR.NormalizeInPlace();
        double leftR = rightLength / Math.Cos(Math.Abs(Math.Atan(this._culvetSlop / 100))); //斜边长度
        DPoint3d rightPoint = DPoint3d.Add(pointA, dVector3DR, leftR);

        DVector3d resultDvecL = dVector3DL.RotateXY(Angle.FromDegrees(leftAngle));
        DVector3d resultDvecR = dVector3DL.RotateXY(Angle.FromDegrees(rightAngle));

        bool isEnterance = false;
        if (leftPoint.Z > rightPoint.Z) isEnterance = true;
        entrancePointInfo = new CulvertPointInfo(leftPoint, resultDvecL, isEnterance, true, slope, normalSlope, Math.Abs(pointA.Z - leftPoint.Z));

        exitPointInfo = new CulvertPointInfo(rightPoint, resultDvecR, !isEnterance, false, slope, normalSlope, Math.Abs(pointA.Z - rightPoint.Z));

        //if (this._culvetSlop >= 0)//下坡
        //{
        //    entrancePointInfo = new CulvertPointInfo(leftPoint, resultDvecL, true, true, slope, normalSlope, Math.Abs(pointA.Z - leftPoint.Z));

        //    exitPointInfo = new CulvertPointInfo(rightPoint, resultDvecR, false, false, slope, normalSlope, Math.Abs(pointA.Z - rightPoint.Z));
        //}
        //else
        //{
        //    entrancePointInfo = new CulvertPointInfo(leftPoint, resultDvecL, false, true, slope, normalSlope, Math.Abs(pointA.Z - leftPoint.Z));

        //    exitPointInfo = new CulvertPointInfo(rightPoint, resultDvecR, true, false, slope, normalSlope, Math.Abs(pointA.Z - rightPoint.Z));
        //}
        return (entrancePointInfo, exitPointInfo);
    }

    public (CulvertPointInfo entrancePointInfo, CulvertPointInfo exitPointInfo) GetPointInfo()
    {
        //路线与涵洞布置线的交点
        //var allIntersectPointOfAlignment = this.GetAllIntersectPointsOfAllAlignment();
        var pointInfo = GetCulvertLayoutInfo();
        var primaryIntersectPoint = this._primaryAlignment.BaseGeometry.ProjectPointOnPerpendicular(this.GetPrimaryIntersectPoint().Coordinates);
        CulvertPointInfo entrancePointInfo = null;
        CulvertPointInfo exitPointInfo = null;

        //if (this._culvetSlop >= 0)//下坡
        //{
        //    var vectorEntrance = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item1.tangentVector); //判断是否和路线同向，不同向时反转
        //    entrancePointInfo = new CulvertPointInfo(pointInfo.Item1.startPoint, vectorEntrance, true, true, pointInfo.Item1.slope, pointInfo.Item1.normalSlope, pointInfo.Item1.fillHeight);

        //    var vectorExit = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item2.tangentVector);
        //    exitPointInfo = new CulvertPointInfo(pointInfo.Item2.endPoint, vectorExit, false, false, pointInfo.Item2.slope, pointInfo.Item2.normalSlope, pointInfo.Item2.fillHeight);
        //}
        //else
        //{
        //    var vectorEntrance = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item1.tangentVector);
        //    entrancePointInfo = new CulvertPointInfo(pointInfo.Item1.startPoint, vectorEntrance, false, true, pointInfo.Item1.slope, pointInfo.Item1.normalSlope, pointInfo.Item1.fillHeight);

        //    var vectorExit = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item2.tangentVector);
        //    exitPointInfo = new CulvertPointInfo(pointInfo.Item2.endPoint, vectorExit, true, false, pointInfo.Item2.slope, pointInfo.Item2.normalSlope, pointInfo.Item2.fillHeight); 
        //}

        bool isEnterance = false;
        if (pointInfo.Item1.startPoint.Z > pointInfo.Item2.endPoint.Z) isEnterance = true;

        var vectorEntrance = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item1.tangentVector); //判断是否和路线同向，不同向时反转
        entrancePointInfo = new CulvertPointInfo(pointInfo.Item1.startPoint, vectorEntrance, isEnterance, true, pointInfo.Item1.slope, pointInfo.Item1.normalSlope, pointInfo.Item1.fillHeight);

        var vectorExit = this.TryReverseVector(primaryIntersectPoint.TangentVector, pointInfo.Item2.tangentVector);
        exitPointInfo = new CulvertPointInfo(pointInfo.Item2.endPoint, vectorExit, !isEnterance, false, pointInfo.Item2.slope, pointInfo.Item2.normalSlope, pointInfo.Item2.fillHeight);
        return (entrancePointInfo, exitPointInfo);
    }

    private List<(DPoint3d point, double slope, double normalSlope)> GetAllIntersectPoints()
    {
        var ret = new List<(DPoint3d point, double slope, double normalSlope)>();

        var line = DraftingElementSchema.ToElement(this.ActiveThreeDModel, this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), null);
        foreach (var corridor in this.AllRefCorridors)
        {
            string name = corridor.Name;
            var readPt = new List<(DPoint3d point, double slope, double normalSlope)>();
            var surfaceEntities1 = corridor.GetFinalSurfaceEntities().Where(p => p.Name.Contains("BP"));
            foreach (var surfaceEntity in surfaceEntities1)
            {
                var lineele = line as LineStringElement;
                var point = GetIntersectPointLineAndSurface(lineele, surfaceEntity);
                if (point.point != null)
                {
                    ret.Add(((DPoint3d)point.point, (double)point.slope, (double)point.normalSlope));
                }
            }
        }
        //ret.Distinct();
        return ret;
    }

    private List<(DPoint3d point, double slope, double normalSlope, double fillHeight, DVector3d tangetVecotr)> GetAllIntersectPoints_H()
    {
        TransformInfo transInfo = new TransformInfo(DTransform3d.Scale(GeneralHelpers.UorToMeters));
        var ret = new List<(DPoint3d point, double slope, double normalSlope, double fillHeight, DVector3d tangetVecotr)>();
        var line = DraftingElementSchema.ToElement(this.ActiveThreeDModel, this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), null);
        foreach (var corridor in this.AllRefCorridors)
        {
            //foreach (TemplateDrop item in corridor.BaseRule.TemplateDrops)
            //{
            //    double startStation = item.StartStation;
            //    double StopStation = item.StopStation;

            //}
            //获取边坡
            var surfaceEntities1 = corridor.GetFinalSurfaceEntities().Where(p => p.Name.Contains("BP"));
            int surfaceEntities1_count = corridor.GetFinalSurfaceEntities().Where(p => p.Name.Contains("BP")).Count();
            //获取三维线
            var linearEntities = corridor.GetFinalLinearEntities();
            var linesEntity = linearEntities.Where(s => s.Name.Contains("PJX-") || s.Name.Contains("PKX-") || s.Name.Contains("LJBY-"));
            // ar pkx_L = linesEntity.Where(s => s.Name == "PKX-L");
            // ar pkx_R = linesEntity.Where(s => s.Name == "PKX-R");
            var ljby_L = linesEntity.Where(s => s.Name == "LJBY-L-1");
            var ljby_R = linesEntity.Where(s => s.Name == "LJBY-R-1");

            int pkx_L_count = linearEntities.Where(s => s.Name == "PKX-L").Count();
            int pkx_R_count = linesEntity.Where(s => s.Name == "PKX-R").Count();
            int ljby_L_count = linesEntity.Where(s => s.Name == "LJBY-L-1").Count();
            int ljby_R_count = linesEntity.Where(s => s.Name == "LJBY-R-1").Count();


            if (pkx_L_count > 0)
            {
                var ljbyPt = GetIntersectXYPoint(ljby_L.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                var pointL = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_L.ToList()[0].BaseGeometry.GetCurveVector());
                double fillHeight = Math.Round(Math.Abs(pointL.point.Value.Z - ljbyPt.point.Value.Z), 3);
                ret.Add(((DPoint3d)pointL.point, (double)pointL.slope, (double)pointL.normalSlope, (double)fillHeight, (DVector3d)ljbyPt.dVector3D));
            }


            if (pkx_R_count > 0)
            {
                var ljbyPt = GetIntersectXYPoint(ljby_R.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                var pointR = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_R.ToList()[0].BaseGeometry.GetCurveVector());
                double fillHeight = Math.Round(Math.Abs(pointR.point.Value.Z - ljbyPt.point.Value.Z), 3);
                ret.Add(((DPoint3d)pointR.point, (double)pointR.slope, (double)pointR.normalSlope, (double)fillHeight, (DVector3d)ljbyPt.dVector3D));
            }

            if (surfaceEntities1_count == 0) continue;


            foreach (var surfaceEntity in surfaceEntities1)
            {
                double fillHeightTF = 0;
                DVector3d dVector3D = new DVector3d();
                if (surfaceEntity.Name.EndsWith("-L"))
                {
                    if (ljby_L_count > 0)
                    {
                        //var pjxLine = DraftingElementSchema.ToElement(this.ActiveThreeDModel, ljby_L.ToList()[0].BaseGeometry.GetCurveVector(), null);
                        //TransformInfo transInfo1 = new TransformInfo(DTransform3d.Scale(GeneralHelpers.UorToMeters));
                        //pjxLine.ApplyTransform(transInfo1);
                        //pjxLine.AddToModel();
                        var ljbyPt = GetIntersectXYPoint(ljby_L.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                        dVector3D = (DVector3d)ljbyPt.dVector3D;
                        var pointL = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_L.ToList()[0].BaseGeometry.GetCurveVector());
                        fillHeightTF = Math.Round(Math.Abs(pointL.point.Value.Z - ljbyPt.point.Value.Z), 3);
                    }
                }
                else if (surfaceEntity.Name.EndsWith("-R"))
                {
                    if (ljby_R_count > 0)
                    {
                        var ljbyPt = GetIntersectXYPoint(ljby_R.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                        dVector3D = (DVector3d)ljbyPt.dVector3D;
                        var pointR = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_R.ToList()[0].BaseGeometry.GetCurveVector());
                        fillHeightTF = Math.Round(Math.Abs(pointR.point.Value.Z - ljbyPt.point.Value.Z), 3);
                    }
                }
                var lineele = line as LineStringElement;
                var point = GetIntersectPointLineAndSurface_H(lineele, surfaceEntity);
                if (point.point != null && point.point != DPoint3d.Zero)
                {
                    ret.Add(((DPoint3d)point.point, (double)point.slope, (double)point.normalSlope, (double)fillHeightTF, dVector3D));
                }
            }
            //var pjxLine = DraftingElementSchema.ToElement(this.ActiveThreeDModel, item.BaseGeometry.GetCurveVector(), null);
        }
        return ret;
    }


    /// <summary>
    /// bim中心版本调用
    /// </summary>
    /// <returns></returns>
    private List<(DPoint3d point, double slope, double normalSlope, double fillHeight, DVector3d tangetVecotr)> GetAllIntersectPoints_H_BIM()
    {
        TransformInfo transInfo = new TransformInfo(DTransform3d.Scale(GeneralHelpers.UorToMeters));
        var ret = new List<(DPoint3d point, double slope, double normalSlope, double fillHeight, DVector3d tangetVecotr)>();
        var line = DraftingElementSchema.ToElement(this.ActiveThreeDModel, this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), null);
        foreach (var corridor in this.AllRefCorridors)
        {
            //获取边坡
            var surfaceEntities1 = corridor.GetFinalSurfaceEntities().Where(p => p.Name.Contains("BP-L") || p.Name.Contains("BP-R"));
            int surfaceEntities1_count = corridor.GetFinalSurfaceEntities().Where(p => p.Name.Contains("BP-L") || p.Name.Contains("BP-R")).Count();
            //获取三维线
            var linearEntities = corridor.GetFinalLinearEntities();
            var linesEntity = linearEntities.Where(s => s.Name == "TF1-L" || s.Name == "WF1-L" || s.Name == "TF1-R" || s.Name == "WF1-R" || s.Name == "LJBY-L" || s.Name == "LJBY-R" || s.Name.Contains("TLJ-EP-"));
            int aa = linesEntity.Count();
            //var pkx_L = linesEntity.Where(s => s.Name == "PKX-L");
            //var pkx_R = linesEntity.Where(s => s.Name == "PKX-R");
            var ljby_L = linesEntity.Where(s => s.Name == "LJBY-L" || s.Name == "TLJ-EP-L");
            var ljby_R = linesEntity.Where(s => s.Name == "LJBY-R" || s.Name == "TLJ-EP-R");

            int pkx_L_count = linearEntities.Where(s => s.Name == "WF1-L").Count();
            int pkx_R_count = linesEntity.Where(s => s.Name == "WF1-R").Count();
            int ljby_L_count = linesEntity.Where(s => s.Name == "LJBY-L" || s.Name == "TLJ-EP-L").Count();
            int ljby_R_count = linesEntity.Where(s => s.Name == "LJBY-R" || s.Name == "TLJ-EP-R").Count();

            if (pkx_L_count > 0)
            {
                var ljbyPt = GetIntersectXYPoint(ljby_L.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                var pointL = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_L.ToList()[0].BaseGeometry.GetCurveVector());
                double fillHeight = Math.Round(Math.Abs(pointL.point.Value.Z - ljbyPt.point.Value.Z), 3);
                ret.Add(((DPoint3d)pointL.point, (double)pointL.slope, (double)pointL.normalSlope, (double)fillHeight, (DVector3d)ljbyPt.dVector3D));
            }


            if (pkx_R_count > 0)
            {
                var ljbyPt = GetIntersectXYPoint(ljby_R.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                var pointR = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_R.ToList()[0].BaseGeometry.GetCurveVector());
                double fillHeight = Math.Round(Math.Abs(pointR.point.Value.Z - ljbyPt.point.Value.Z), 3);
                ret.Add(((DPoint3d)pointR.point, (double)pointR.slope, (double)pointR.normalSlope, (double)fillHeight, (DVector3d)ljbyPt.dVector3D));
            }

            if (surfaceEntities1_count == 0) continue;
            foreach (var surfaceEntity in surfaceEntities1)
            {
                double fillHeightTF = 0;
                DVector3d dVector3D = new DVector3d();
                if (surfaceEntity.Name.Contains("-L"))
                {
                    if (ljby_L.ToList().Count > 0)
                    {
                        var ljbyPt = GetIntersectXYPoint(ljby_L.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                        dVector3D = (DVector3d)ljbyPt.dVector3D;
                        var pointL = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_L.ToList()[0].BaseGeometry.GetCurveVector());
                        fillHeightTF = Math.Round(Math.Abs(pointL.point.Value.Z - ljbyPt.point.Value.Z), 3);
                    }
                }
                else if (surfaceEntity.Name.Contains("-R"))
                {
                    if (ljby_R.ToList().Count > 0)
                    {
                        var ljbyPt = GetIntersectXYPoint(ljby_R.ToList()[0].BaseGeometry.GetCurveVector(), this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector());
                        dVector3D = (DVector3d)ljbyPt.dVector3D;
                        var pointR = GetIntersectXYPoint(this._culvertLayoutLine.ActiveLinearEntity3dValidBaseGeometry.GetCurveVector(), ljby_R.ToList()[0].BaseGeometry.GetCurveVector());
                        fillHeightTF = Math.Round(Math.Abs(pointR.point.Value.Z - ljbyPt.point.Value.Z), 3); //右侧填土高度
                    }
                }
                var lineele = line as LineStringElement;

                var point = GetIntersectPointLineAndSurface_H_BIM(lineele, surfaceEntity);
                if (point.point != null && point.point != DPoint3d.Zero)
                {
                    ret.Add(((DPoint3d)point.point, (double)point.slope, (double)point.normalSlope, (double)fillHeightTF, dVector3D));
                }
            }
            //var pjxLine = DraftingElementSchema.ToElement(this.ActiveThreeDModel, item.BaseGeometry.GetCurveVector(), null);
        }
        return ret;
    }


    private (DPoint3d? point, double? slope, double? normalSlope) GetIntersectPointLineAndSurface_H(LineStringElement lineElement, SurfaceEntity surfaceEntity)
    {
        //var line = lineElement.GetCurveVector().Clone();
        //line.GetStartEnd(out var startPoint, out var endPoint);
        //var meshSurfaceEntity = surfaceEntity as MeshSurfaceEntity;
        //PolyfaceHeader polyface = meshSurfaceEntity.Surface.Polyface;
        //DTransform3d dTransform3D = DTransform3d.Scale(GeneralHelpers.UorToMeters);
        //polyface.Transform(ref dTransform3D, false);
        //var drapLine = polyface.DrapeLinestring(new List<DPoint3d>() { startPoint * GeneralHelpers.UorToMeters, endPoint * GeneralHelpers.UorToMeters }, DVector3d.UnitZ);
        var line = lineElement.GetCurveVector().Clone();
        line.GetStartEnd(out var startPoint, out var endPoint);
        var meshSurfaceEntity = surfaceEntity as MeshSurfaceEntity;
        var drapLine = meshSurfaceEntity.Surface.Polyface.DrapeLinestring(new List<DPoint3d>() { startPoint, endPoint }, DVector3d.UnitZ);
        if (drapLine == null)
        {
            return (null, null, null);
        }
        drapLine.GetStartEnd(out var drapLineStaPt, out var drapLineEndPt);
        //var drapLineCopy = drapLine.Clone();

        List<DPoint3d> points = new List<DPoint3d>();
        drapLine.GetPrimitive(0).TryGetLineString(points);

        //判断最低点
        if (drapLineStaPt.Z < drapLineEndPt.Z)
        {
            points.Reverse();
        }
        DPoint3d upPt = new DPoint3d();
        DPoint3d downPt = new DPoint3d();
        upPt = points[points.Count - 2];
        downPt = points[points.Count - 1];
        //添加至模型
        //DTransform3d dTransform3D = DTransform3d.FromMatrixAndFixedPoint(DMatrix3d.Scale(10), new DPoint3d((drapLineStaPt.X + drapLineEndPt.X) / 2 , (drapLineStaPt.Y + drapLineEndPt.Y) / 2, (drapLineStaPt.Z + drapLineEndPt.Z) / 2) * GeneralHelpers.UorToMeters);
        //TransformInfo transInfo1 = new TransformInfo(DTransform3d.Scale(GeneralHelpers.UorToMeters));
        //TransformInfo transInfo2 = new TransformInfo(dTransform3D);

        //Bentley.DgnPlatformNET.Elements.LineStringElement jxEle = (LineStringElement)DraftingElementSchema.ToElement(this.ActiveThreeDModel, drapLineCopy, null);
        //jxEle.ApplyTransform(transInfo1);
        //jxEle.ApplyTransform(transInfo2);
        //jxEle.AddToModel();


        //DTransform3d dTransform3D = DTransform3d.FromMatrixAndFixedPoint(DMatrix3d.Scale(10), new DPoint3d((drapLineStaPt.X + drapLineEndPt.X) / 2, (drapLineStaPt.Y + drapLineEndPt.Y) / 2, (drapLineStaPt.Z + drapLineEndPt.Z) / 2));
        //drapLineCopy.Transform(dTransform3D);
        DVector3d dVector3D = new DVector3d(upPt, downPt);
        dVector3D.NormalizeInPlace();
        DPoint3d rightPoint = DPoint3d.Add(upPt, dVector3D, 1000);
        points[points.Count - 1] = rightPoint;
        Bentley.CifNET.LinearGeometry.LineString lineString = new Bentley.CifNET.LinearGeometry.LineString(points.ToArray());

        DPoint3d point = GetIntersectXYZPoint(line, lineString.GetCurveVector());
        drapLine.GetStartEnd(out var startPoint1, out var endPoint1);

        DPoint3d vPoint = new DPoint3d(startPoint1.X, startPoint1.Y, endPoint1.Z);
        var slope = vPoint.Distance(startPoint1) / vPoint.Distance(endPoint1);
        //DVector3d vVector3D = new DVector3d(startPoint1, vPoint);
        //DVector3d xVector3D = new DVector3d(startPoint1, endPoint1);
        //Angle angle = vVector3D.AngleTo(xVector3D);

        //var slope = (endPoint1.Z - startPoint1.Z) / (endPoint1.X - startPoint1.X);
        var descriptionPropertyInfo = surfaceEntity.GetType().GetProperty("Description", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

        var value = descriptionPropertyInfo.GetValue(surfaceEntity);
        var normalSlope = 0.0;
        if (value != null && value.ToString().Trim() != "")
        {
            var values = value.ToString().Split(',');
            normalSlope = Convert.ToDouble(values[1]);
        }
        return (point, slope, normalSlope);
    }


    /// <summary>
    /// bim中心调用
    /// </summary>
    /// <param name="lineElement"></param>
    /// <param name="surfaceEntity"></param>
    /// <returns></returns>
    private (DPoint3d? point, double? slope, double? normalSlope) GetIntersectPointLineAndSurface_H_BIM(LineStringElement lineElement, SurfaceEntity surfaceEntity)
    {
        //var line = lineElement.GetCurveVector().Clone();
        //line.GetStartEnd(out var startPoint, out var endPoint);
        //var meshSurfaceEntity = surfaceEntity as MeshSurfaceEntity;
        //PolyfaceHeader polyface = meshSurfaceEntity.Surface.Polyface;
        //DTransform3d dTransform3D = DTransform3d.Scale(GeneralHelpers.UorToMeters);
        //polyface.Transform(ref dTransform3D, false);
        ////PolyfaceHeader polyfaceHeader =ElementProcess.CreateShapeRepresentation_Polyface(meshSurfaceEntity.Surface.Polyface);//三角面片
        //var drapLine = polyface.DrapeLinestring(new List<DPoint3d>() { startPoint * GeneralHelpers.UorToMeters, endPoint * GeneralHelpers.UorToMeters }, DVector3d.UnitZ);
        //if (drapLine == null)
        //{
        //    return (null, null, null);
        //}

        var line = lineElement.GetCurveVector().Clone();
        line.GetStartEnd(out var startPoint, out var endPoint);
        var meshSurfaceEntity = surfaceEntity as MeshSurfaceEntity;
        var drapLine = meshSurfaceEntity.Surface.Polyface.DrapeLinestring(new List<DPoint3d>() { startPoint, endPoint }, DVector3d.UnitZ);
        if (drapLine == null)
        {
            return (null, null, null);
        }

        drapLine.GetStartEnd(out var drapLineStaPt, out var drapLineEndPt);
        //drapLineStaPt = drapLineStaPt * (1 / GeneralHelpers.UorToMeters);
        //drapLineEndPt = drapLineEndPt * (1 / GeneralHelpers.UorToMeters);
        List<DPoint3d> points = new List<DPoint3d>();
        drapLine.GetPrimitive(0).TryGetLineString(points);

        //判断最低点
        if (drapLineStaPt.Z < drapLineEndPt.Z)
        {
            points.Reverse();
        }
        DPoint3d upPt = new DPoint3d();
        DPoint3d downPt = new DPoint3d();
        upPt = points[points.Count - 2];
        downPt = points[points.Count - 1];

        //添加至模型
        //DTransform3d dTransform3D = DTransform3d.FromMatrixAndFixedPoint(DMatrix3d.Scale(10), drapLineStaPt * GeneralHelpers.UorToMeters);
        //TransformInfo transInfo1 = new TransformInfo(DTransform3d.Scale(GeneralHelpers.UorToMeters));
        //TransformInfo transInfo2 = new TransformInfo(dTransform3D);
        //Bentley.DgnPlatformNET.Elements.LineStringElement jxEle = (LineStringElement)DraftingElementSchema.ToElement(this.ActiveThreeDModel, drapLineCopy, null);
        //jxEle.ApplyTransform(transInfo1);
        //jxEle.ApplyTransform(transInfo2);
        //jxEle.AddToModel();

        DVector3d dVector3D = new DVector3d(upPt, downPt);
        dVector3D.NormalizeInPlace();
        DPoint3d rightPoint = DPoint3d.Add(upPt, dVector3D, 1000);
        points[points.Count - 1] = rightPoint;
        Bentley.CifNET.LinearGeometry.LineString lineString = new Bentley.CifNET.LinearGeometry.LineString(points.ToArray());
        //放大投影线
        //DTransform3d dTransformScal = DTransform3d.FromMatrixAndFixedPoint(DMatrix3d.Scale(10), drapLineStaPt * GeneralHelpers.UorToMeters);
        //drapLineCopy.Transform(dTransformScal);
        //CNCCBIM 边坡处理
        DPoint3d point = GetIntersectXYZPoint(line, lineString.GetCurveVector());
        DPoint3d resultPt = new DPoint3d();
        double len = 9999999999;
        foreach (var item in points)
        {
            if (point.Distance(item) < len) resultPt = item;
        }

        DPoint3d vPoint = new DPoint3d(point.X, point.Y, resultPt.Z);
        var slope = vPoint.Distance(point) / vPoint.Distance(resultPt);
        var normalSlope = slope;
        return (point, slope, normalSlope);
    }


    private DPoint3d GetIntersectXYZPoint(CurveVector outCurveVectorA, CurveVector curveVectorB)
    {
        outCurveVectorA.GetStartEnd(out var startPointA, out var endPointA);
        curveVectorB.GetStartEnd(out var startPointB, out var endPointB);
        CurveVector intersectionA = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveVector intersectionB = new CurveVector(CurveVector.BoundaryType.Inner);

        DMatrix3d dMatrix3D = CE单位矩阵(startPointA, endPointA, startPointB);
        //在4x4矩阵中，总共时16个浮点数，默认的单位矩阵如下：
        //若仅用于空间计算，则只看矩阵的前三行即可，
        //第一列的（1，0，0）代表X轴，
        //第二列的（0，1，0）代表Y轴，
        //第三列的（0，0，1）代表Z轴，
        //第四列的（0，0，0）代表空间位置。
        //此外，第四行永远为（0，0，0，1）。
        DMatrix4d dMatrix4D = new DMatrix4d(
                    dMatrix3D.ColumnX.X,
                    dMatrix3D.ColumnX.Y,
                    dMatrix3D.ColumnX.Z,
                    0,
                    dMatrix3D.ColumnY.X,
                    dMatrix3D.ColumnY.Y,
                    dMatrix3D.ColumnY.Z,
                    0,
                    dMatrix3D.ColumnZ.X,
                    dMatrix3D.ColumnZ.Y,
                    dMatrix3D.ColumnZ.Z,
                    0,
                    0, 0, 0, 1);

        CurveCurve.IntersectionsXY(intersectionA, intersectionB, outCurveVectorA, curveVectorB, dMatrix4D);//DMatrix4d.From(dTransform3));
        intersectionB.GetStartPoint(out var point);
        return point;
    }
    private (DPoint3d? point, double? slope, double? normalSlope, DVector3d? dVector3D) GetIntersectXYPoint(CurveVector outCurveVectorA, CurveVector curveVectorB)
    {
        outCurveVectorA.GetStartEnd(out var startPointA, out var endPointA);
        curveVectorB.GetStartEnd(out var startPointB, out var endPointB);
        CurveVector intersectionA = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveVector intersectionB = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveCurve.IntersectionsXY(intersectionA, intersectionB, outCurveVectorA, curveVectorB);//DMatrix4d.From(dTransform3));
        intersectionA.GetStartEnd(out DPoint3d pointA, out DPoint3d pointB, out DVector3d unitTangentA, out DVector3d unitTangentB);

        var slope = Math.Abs((endPointA.Y - startPointA.Y) / (endPointA.X - startPointA.X));
        long count = outCurveVectorA.ClosestPointBoundedXY(pointA).NumberComponent;
        long index = outCurveVectorA.ClosestPointBoundedXY(pointA).ComponentIndex;
        CurveLocationDetail curveLocationDetail = outCurveVectorA.ClosestPointBoundedXY(pointA);
        double fraction = outCurveVectorA.ClosestPointBoundedXY(pointA).Fraction;
        int aa = outCurveVectorA.Count();
        outCurveVectorA.GetPrimitive(0).FractionToPoint(fraction, out DPoint3d startPoint1, out DVector3d startTangent);
        //Bentley.DgnPlatformNET.Elements.LineElement lineElement = new Bentley.DgnPlatformNET.Elements.LineElement(
        //    Session.Instance.GetActiveDgnModel(), null, new DSegment3d(pointA * GeneralHelpers.UorToMeters, DPoint3d.Add(pointA, startTangent, 10.0) * GeneralHelpers.UorToMeters));
        //lineElement.AddToModel();

        return (pointA, 1 / 1.5, 1 / 1.5, startTangent);
    }
    public static DMatrix3d CE单位矩阵(DPoint3d D矩阵原点, DPoint3d D矩阵X轴点, DPoint3d D矩阵Y轴点)
    {
        DMatrix3d rMatrix = new DMatrix3d();
        DVector3d V矩阵原点 = new DVector3d(D矩阵原点);
        DVector3d V矩阵X轴点 = new DVector3d(D矩阵X轴点);
        DVector3d V矩阵Y轴点 = new DVector3d(D矩阵Y轴点);

        DVector3d X轴单位向量 = new DVector3d();
        DVector3d Y轴单位向量 = new DVector3d();
        DVector3d Z轴单位向量 = new DVector3d();
        DVector3d Dnum = new DVector3d();

        //X轴单位向量
        Dnum = DVector3d.Subtract(V矩阵X轴点, V矩阵原点);
        //单位向量
        Dnum.NormalizeInPlace();
        //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
        X轴单位向量 = Dnum;

        //Y轴单位向量
        Dnum = DVector3d.Subtract(V矩阵Y轴点, V矩阵原点);
        //单位向量
        Dnum.NormalizeInPlace();
        //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
        Y轴单位向量 = Dnum;

        //Z轴单位向量
        Dnum = DVector3d.CrossProduct(X轴单位向量.X, X轴单位向量.Y, X轴单位向量.Z, Y轴单位向量.X, Y轴单位向量.Y, Y轴单位向量.Z);
        //单位向量
        Dnum.NormalizeInPlace();
        //MessageBox.Show(Convert.ToString(DVector3d.Zero.Distance(Dnum)));
        Z轴单位向量 = Dnum;

        DVector3d DVX = new DVector3d(X轴单位向量.X, Y轴单位向量.X, Z轴单位向量.X);
        DVector3d DVY = new DVector3d(X轴单位向量.Y, Y轴单位向量.Y, Z轴单位向量.Y);
        DVector3d DVZ = new DVector3d(X轴单位向量.Z, Y轴单位向量.Z, Z轴单位向量.Z);

        rMatrix = DMatrix3d.FromRows(DVX, DVY, DVZ);

        //MessageBox.Show(Convert.ToString(rMatrix.RowX.X + "/" + rMatrix.RowX.Y + "/" + rMatrix.RowX.Z));
        //MessageBox.Show(Convert.ToString(rMatrix.RowY.X + "/" + rMatrix.RowY.Y + "/" + rMatrix.RowY.Z));
        //MessageBox.Show(Convert.ToString(rMatrix.RowZ.X + "/" + rMatrix.RowZ.Y + "/" + rMatrix.RowZ.Z));

        return rMatrix;
    }

    private List<(LinearPoint intersectPoint, LinearEntity2dInPlan alignment)> GetAllIntersectPointsOfAllAlignment()
    {
        var ret = new List<(LinearPoint intersectPoint, LinearEntity2dInPlan alignment)>();
        ret.Add((this._culvertLayoutLine.BaseGeometry.Intersect(this._primaryAlignment.BaseGeometry).Item(0).PointOn1, this._primaryAlignment));
        foreach (var item in this._minorAligmentList)
        {
            ret.Add((this._culvertLayoutLine.BaseGeometry.Intersect(item.BaseGeometry).Item(0).PointOn1, item));
        }
        ret.OrderBy(p => p.intersectPoint.DistanceAlong).ToList();
        return ret;
    }

    private List<Corridor> GetAllRefCorridors()
    {
        var ret = new List<Corridor>();
        // 筛选主线设计廊道
        var primaryCorridors = this.GeometricModel.CorridorSet.Corridors.ToList().Where(cor => cor.BaseRule.TrueBaseHorizontal.Name == this._primaryAlignment.Name).ToList();
        ret.AddRange(primaryCorridors);
        foreach (var al in this._minorAligmentList)
        {
            foreach (var cor in this.GeometricModel.CorridorSet.Corridors)
            {
                if (cor.BaseRule.TrueBaseHorizontal.Name == al.Name)
                {
                    ret.Add(cor);
                } 
            }
        }
        return ret;
    }

    private (DPoint3d? point, double? slope, double? normalSlope) GetIntersectPointLineAndSurface(LineStringElement lineElement, SurfaceEntity surfaceEntity)
    {
        var line = lineElement.GetCurveVector().Clone();
        line.GetStartEnd(out var startPoint, out var endPoint);
        var meshSurfaceEntity = surfaceEntity as MeshSurfaceEntity;
        var drapLine = meshSurfaceEntity.Surface.Polyface.DrapeLinestring(new List<DPoint3d>() { startPoint, endPoint }, DVector3d.UnitZ);
        //if (drapLine == null)
        //    drapLine = meshSurfaceEntity.Surface.Polyface.DrapeLinestring(new List<DPoint3d>() { startPoint, endPoint }, DVector3d.UnitX);
        //if (drapLine == null)
        //    drapLine = meshSurfaceEntity.Surface.Polyface.DrapeLinestring(new List<DPoint3d>() { startPoint, endPoint }, DVector3d.UnitY);
        if (drapLine == null)
        {
            return (null, null, null);
        }

        var matrix = DMatrix3d.FromColumns(this.PrimaryIntersectPointOnCulvertLayLine.TangentVector, DVector3d.UnitZ, this.PrimaryIntersectPointOnCulvertLayLine.NormalVector);
        var transfrom = DTransform3d.FromMatrixAndFixedPoint(matrix, this.PrimaryIntersectPointOnCulvertLayLine.Coordinates);
        var inverseTransform = DTransform3d.FromPseudoInverse(transfrom);
        line.Transform(inverseTransform);
        drapLine.Transform(inverseTransform);
        //DraftingElementSchema.ToElement(GeneralHelpers.ActiveDgnModel, line, null).AddToModel();
        //DraftingElementSchema.ToElement(GeneralHelpers.ActiveDgnModel, drapLine, null).AddToModel();
        drapLine.GetStartEnd(out var startPoint1, out var endPoint1);
        double a = (endPoint1.Y - startPoint1.Y);
        double b = (endPoint1.X - startPoint1.X);
        var slope = Math.Abs((endPoint1.Y - startPoint1.Y) / (endPoint1.X - startPoint1.X));
        var lineEle = DraftingElementSchema.ToElement(this.ActiveThreeDModel, line, null);
        var drapEle = DraftingElementSchema.ToElement(this.ActiveThreeDModel, drapLine, null);
        //ElementHelper.GetMeterToUorElement(lineEle).AddToModel();
        //ElementHelper.GetMeterToUorElement(drapEle).AddToModel();
        CurveVector intersectionA = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveVector intersectionB = new CurveVector(CurveVector.BoundaryType.Inner);
        CurveCurve.IntersectionsXY(intersectionA, intersectionB, line, drapLine);
        intersectionA.GetStartPoint(out var point);
        lineElement.GetCurveVector().ElementAt(0).FractionToPoint(line.ClosestPointBounded(point).Fraction, out var point1);

        var descriptionPropertyInfo = surfaceEntity.GetType().GetProperty("Description", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);

        var value = descriptionPropertyInfo.GetValue(surfaceEntity);
        var normalSlope = 0.0;
        if (value != null)
        {
            var values = value.ToString().Split(',');
            normalSlope = Convert.ToDouble(values[1]);
        }
        //surfaceEntity.GetItemTypeExtension()
        return (point1, slope, normalSlope);
    }

    private List<(DPoint3d point, double disAlong, double slope, double normalSlope, double fillHeight, DVector3d tangentVector)> GetPointInfoList()
    {
        var ret = new List<(DPoint3d point, double disAlong, double slope, double normalSlope, double fillHeight, DVector3d tangentVector)>();
        //var points = this.GetAllIntersectPoints();
        var points = Commands.isBimCenter ? this.GetAllIntersectPoints_H_BIM() : this.GetAllIntersectPoints_H();
        foreach (var item in points)
        {
            ret.Add((item.point, item.point.Distance(this._culvertLayoutLine.ActiveLinearEntity3d.BaseGeometry.StartPoint.Coordinates), item.slope, item.normalSlope, item.fillHeight, item.tangetVecotr));
        }
        return ret;
    }

    private LinearPoint GetPrimaryIntersectPoint()
    {
        var ret = this._primaryAlignment.BaseGeometry.Intersect(this._culvertLayoutLine.BaseGeometry).Item(0).PointOn2;
        return ret;
    }

    private DVector3d TryReverseVector(DVector3d baseVector, DVector3d vector)
    {
        return baseVector.DotProduct(vector) < 0 ? -vector : vector;
    }
}